package com.ash.dao.imp;

import com.ash.dao.IDao;
import com.ash.dao.SqlObjectList;
import com.ash.entity.Count;
import com.ash.util.ConnectionsUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.*;


/**
 * @encoding : UTF-8
 * @time : 2020/12/9 20:54
 * @author : Chen Chao
 * @File : TestLogin02.com.ash.dao.dao.imp.IDaoImpl.java
 * @Software : IntelliJ IDEA
 * @since : 1.8
 */
public class DaoImpl<T> implements IDao<T> {
    private Class<T> typeClass;
    protected String className;
    private String key;
    protected  QueryRunner qr = new QueryRunner(ConnectionsUtil.getDataSource());
    public DaoImpl(Class<T> typeClass, String key) {
        this.typeClass = typeClass;
        className=typeClass.getSimpleName().toLowerCase();
        this.key = key;
    }

    @Override
    public int add(T t) {
        SqlObjectList sqlList = getSqlList(t,",");
        T t1 = selectByKey(sqlList.getKeyObject());

        if(t1!=null){
            System.out.println("主键重复");
            return 0;
        }

        String sql="insert into "+className+" ("+ sqlList.getListString()+") values ";
        ArrayList<Object> objects = sqlList.getObjects();
        StringBuilder valueString = new StringBuilder();
        for (int i = 0; i < objects.size(); i++) {
            valueString.append("?,");
        }
        String valueStr ="(" +valueString.substring(0, valueString.lastIndexOf(","))+")";
        try {
            return qr.update(sql+valueStr , objects.toArray());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return 0;
    }

    @Override
    public T selectByKey(Object key) {
        String sql="select * from "+className+" where "+this.key+" =?";

        try {
            List<T>  query = qr.query(sql, new BeanListHandler<>(typeClass), key);
            if(query!=null&&query.size()!=0){
                return query.get(0);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    @Override
    public List<T> select(T t) {
        String sql="select * from "+className+" where ";
        try {
            SqlObjectList list = getSqlList(t,"and");
            return qr.query(sql+list.getString(),
                    new BeanListHandler<>(typeClass),list.getObjects().toArray());
        } catch ( SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    private SqlObjectList getSqlList(T t,String delimiter) {
        SqlObjectList sqlObjectList = new SqlObjectList();
        HashMap<String, Object> map = getClassMap(t);
        Set<Map.Entry<String, Object>> entries = map.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            System.out.println(entry.getKey()+":"+entry.getValue());
        }
        ArrayList<Object> objects = new ArrayList<>();

        /*BeanUtils取出所有属性,拼接成查询语句*/
        StringBuilder str = new StringBuilder();
        StringBuilder listStr = new StringBuilder();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if(entry.getKey().equals(this.key)){
                sqlObjectList.setKeyObject(entry.getValue());
            }
            if(entry.getValue()!=null){
                str.append(entry.getKey()).append("=").append("? ").append(delimiter).append(" ");
                listStr.append(entry.getKey()).append(",");
                objects.add(entry.getValue());
            }
        }
        /*转换成String并去掉最后的and*/
        String string =str+"";
        String listString=listStr+"";
        /*打包返回*/
        sqlObjectList.setObjects(objects);
        if(str.lastIndexOf(delimiter)!=-1){
            sqlObjectList.setString(string.substring(0, str.lastIndexOf(delimiter)));
        }
        if(listString.lastIndexOf(",")!=-1){
            sqlObjectList.setListString(listString.substring(0, listString.lastIndexOf(",")));
        }
        return sqlObjectList;

    }

    /**
     * 把实例对象转换成hashMap
     * @param t 要转换的实例对象
     * @return  转换好的hashMap
     */
    private HashMap<String, Object> getClassMap(T t)  {
        HashMap<String, Object> map = new HashMap<>(10);
        try {
            /*获取字节码信息*/
            BeanInfo beanInfo = Introspector.getBeanInfo(typeClass, Object.class);
            /*获取字段信息*/
            PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor pd : pds) {
                map.put(pd.getName(),pd.getReadMethod().invoke(t));
            }
        } catch (IllegalAccessException | InvocationTargetException | IntrospectionException e) {
            e.printStackTrace();
        }
        return map;
    }


    @Override
    public List<T> selectAll() {
        String sql="select * from "+className;
        try {
            return qr.query(sql, new BeanListHandler<>(typeClass));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public int deleteByKey(Object key) {
        if(selectByKey(key)==null){
            System.out.println("不存在实例对象");
            return 0;
        }
        String sql="delete from "+className+" where "+this.key+"=?";
        try {
            return qr.update(sql, key);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return 0;
    }

    @Override
    public int delete(T t) {
        String sql="delete from "+className+" where ";
        try {
            SqlObjectList list = getSqlList(t,"and");
            return qr.update(sql+list.getString(),list.getObjects().toArray());
        } catch ( SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }

    @Override
    public int modify(T t) {
        String sql="update "+className+" set ";
        try {
            SqlObjectList list = getSqlList(t,",");
            System.out.println(sql+list.getString()+" where "+this.key+" =?");
            /*加上最后的key对应的Object*/
            ArrayList<Object> objects = list.getObjects();
            objects.add(list.getKeyObject());

            return qr.update(sql+list.getString()+" where "+this.key+" =?",
                    objects.toArray());
        } catch ( SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }


    @Override
    public int count() {
        String sql="select count(*) as count from "+className;
        try {
            return qr.query(sql,new BeanHandler<>(Count.class)).getCount();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return 0;
    }

    public Class<T> getTypeClass() {
        return typeClass;
    }

    public void setTypeClass(Class<T> typeClass) {
        this.typeClass = typeClass;
    }


    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }
}
